# service/parse/local_upload.py
import io
import os

from common.exception.exception import BusiException
from common.exception.exception_enum import BusiExceptionEnum
from common.log.logging import log
from common.oss.oss import OssApi, OssObject
from common.utils.id_utils import get_uuid


class OssLocal(OssApi):
    def __init__(self, base_path: str, default_bucket: str):
        self.base_path = base_path
        self.default_bucket = default_bucket

    def upload(self, filename: str, stream: io.IOBase) -> OssObject:
        """
        文件上传到默认的bucket
        :param filename: 文件名称
        :param stream: 上传的文件
        :return: OssObject
        """
        return self.upload_to_bucket(self.default_bucket, filename, stream)

    def upload_to_bucket(self, bucket_name: str, filename: str, stream: io.IOBase) -> OssObject:
        """
        上传文件到本地文件系统。

        参数:
        - stream: io.IOBase 对象，表示上传的文件。

        返回:
        - OssObject 对象，包含桶名称和对象 ID。
        """
        if not stream:
            raise BusiException(BusiExceptionEnum.NO_FILE_PART)

        unique_filename = f"{get_uuid()}{os.path.splitext(filename)[1]}"
        bucket_path = os.path.join(self.base_path, bucket_name)
        file_path = os.path.join(bucket_path, unique_filename)

        try:
            # 确保上传目录存在
            os.makedirs(bucket_path, exist_ok=True)
            with open(file_path, 'wb') as f:
                f.write(stream.read())
            log.debug(f'File {filename} successfully uploaded to {file_path}')
            return OssObject(bucket_name, unique_filename)
        except Exception as e:
            log.error(f'Error uploading file: {e}')
            raise BusiException(BusiExceptionEnum.OSS_FILE_UPLOAD_ERROR)

    def get_object(self, object_id: str):
        return self.get_object_from_bucket(self.default_bucket, object_id)

    def get_object_from_bucket(self, bucket_name: str, object_id: str) -> io.IOBase:
        """
        从本地文件系统中获取对象。

        参数:
        - bucket_name: 存储路径
        - object_id: 对象 ID

        返回:
        - io.IOBase 对象，表示获取的文件。
        """
        bucket_path = os.path.join(self.base_path, bucket_name)
        file_path = os.path.join(bucket_path, object_id)

        try:
            if not os.path.exists(file_path):
                raise BusiException(BusiExceptionEnum.OSS_OBJECT_NOT_EXISTS)

            with open(file_path, 'rb') as f:
                file_stream = io.BytesIO(f.read())
                file_stream.seek(0)
                log.info(f'File {object_id} successfully retrieved from {bucket_name}')
                return file_stream
        except Exception as e:
            log.error(f'Error retrieving file: {e}')
            raise BusiException(BusiExceptionEnum.OSS_FILE_RETRIEVAL_ERROR)
